package com.feng.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.feng.entity.ArticleTag;
import com.feng.entity.RestResponse;
import com.feng.entity.Role;
import com.feng.entity.vo.*;
import com.feng.exception.SystemException;
import com.feng.mapper.TagMapper;
import com.feng.entity.Tag;
import com.feng.service.ArticleTagService;
import com.feng.service.TagService;
import com.feng.utils.HttpCodeEnum;
import com.feng.utils.WebUtils;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * (Tag)表服务实现类
 *
 * @author feng
 * @since 2024-10-18 13:57:29
 */
@Service()
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements TagService {

    final
    ArticleTagService articleTagService;

    public TagServiceImpl(ArticleTagService articleTagService) {
        this.articleTagService = articleTagService;
    }

    @Override
    public RestResponse listAllTag() {
        List<Tag> tagList = list();
        List<TagAllListVo>  tagAllListVoList = new ArrayList<>();
        tagList.stream().parallel()
                .forEach(category -> {
                    tagAllListVoList.add(new TagAllListVo(category.getId(), category.getName()));
                });
        return RestResponse.success(tagAllListVoList);
    }

    @Override
    public RestResponse listAllPageTag(TagPageReqVo tagPage) {
        LambdaQueryWrapper<Tag> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Objects.nonNull(tagPage.getName()), Tag::getName, tagPage.getName());
        Page page = new Page(tagPage.getCurrent(), tagPage.getSize());
        page(page, wrapper);
        List<Tag> tags = page.getRecords();
        List<TagPageRespVo>  tagPageRespVoList = new ArrayList<>();
        tags.stream()
                .forEach(tag -> {
                    tagPageRespVoList.add(new TagPageRespVo(tag.getId(), tag.getName(), tag.getCreateTime()));
                });
        return RestResponse.success(new ArticleListPageVo(tagPageRespVoList, page.getTotal()));
    }

    @Override
    public RestResponse addTag(TagAddVo tagAdd) {
        if(tagNameExist(tagAdd.getName())) throw new SystemException(HttpCodeEnum.TAG_NAME_EXIST);
        getBaseMapper().AUTO_INCREMENT();
        Tag tag = new Tag();
        tag.setName(tagAdd.getName());
        save(tag);
        return RestResponse.success();
    }

    @Override
    public RestResponse getTagById(Long id) {
        Tag tag = getById(id);
        if(Objects.isNull(tag)) throw new SystemException(HttpCodeEnum.TAG_NOT_EXIST);
        TagAddVo tagAddVo = new TagAddVo(tag.getId(), tag.getName());
        return RestResponse.success(tagAddVo);
    }

    @Override
    public RestResponse updateTag(TagAddVo tagAdd) {
        Tag tag = new Tag();
        tag.setId(tagAdd.getId()).setName(tagAdd.getName());
        updateById(tag);
        return RestResponse.success();
    }

    @Transactional
    @Override
    public RestResponse deleteTag(Long id) {
        Tag tag = getById(id);
        if(Objects.isNull(tag)) throw new SystemException(HttpCodeEnum.TAG_NOT_EXIST);
        LambdaQueryWrapper<ArticleTag>  wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ArticleTag::getTagId, id);
        articleTagService.remove(wrapper);
        removeById(id);
        return RestResponse.success();
    }

    @Transactional
    @Override
    public RestResponse delBatchTag(List<Long> ids) {
        LambdaQueryWrapper<ArticleTag>  wrapper = new LambdaQueryWrapper<>();
        ids.stream()
                .forEach(id -> {
                    wrapper.eq(ArticleTag::getTagId, id);
                    articleTagService.remove(wrapper);
                    wrapper.clear();
                });
        removeBatchByIds(ids);
        return RestResponse.success();
    }

    @Override
    public void export(HttpServletResponse response) {
        try (ServletOutputStream outputStream = response.getOutputStream()){
            WebUtils.excelResponseHeader(response, "标签");
            List<Tag> tags = list();
            List<TagExportVo> exportVo = new ArrayList<>();
            tags.forEach(tag -> exportVo.add(new TagExportVo(tag.getId(), tag.getName(), tag.getCreateTime())));
            EasyExcel.write(outputStream, TagExportVo.class)
                    .autoCloseStream(Boolean.FALSE).sheet("标签导出")
                    .doWrite(exportVo);
        } catch (Exception e) {
            response.reset();
            WebUtils.renderString(response, RestResponse.failure(500, "标签导出出现了错误").asJsonString());
        }
    }

    private boolean tagNameExist(String name) {
        LambdaQueryWrapper<Tag> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Tag::getName, name);
        long count = count(wrapper);
        return count > 0;
    }
}

